home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Sample Code / Snippets / Interapplication Communication / AECDEV⁄AEDAEMON / AEDaemonPPCStuff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-15  |  8.6 KB  |  244 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2. #
  3. #   Apple Developer Technical Support
  4. #
  5. #   AEDeamon
  6. #   A small faceless background-only application
  7. #
  8. #   AEDeamonPPCStuff.c  -   C Source
  9. #
  10. #   Copyright © 1991 Apple Computer, Inc.
  11. #   All rights reserved.
  12. #
  13. #   Versions:   
  14. #               1.0               08/91       C.K. Haun <TR>
  15. #   
  16. #   Components:
  17. #                           AEDeamonMain.c
  18. #                           AEDeamonAEvents.c
  19. #                            AEDeamonPPCStuff.c
  20. --------------------------------------------------------------------------------*/
  21. /*------------------------------------------------------------------------------
  22. #    This file contains all the PPC stuff for the AEDeamon.  It reads the AppleEvent
  23. #    data from the PPC channel, puts it in an AEDesc, and fires it for AESend.
  24. #    That's all it does.  But _not_ all it could do.  If the sender wanted a reply,
  25. #    the Deamon could send the reply back through the same channel the event came through.
  26. #    This sample does the minimum, but you can expand it reasonably easily to 
  27. #    give full AppleEvent support to any DA/INIT/CDEV/DRIVER you want.
  28. --------------------------------------------------------------------------------*/
  29.  
  30.  
  31. #define __BUILDINGDEAMON__
  32. #define __AEDPPCSTUFF__
  33.  
  34. #include "NonAppAEVT.h"
  35.  
  36.  
  37. Handle dataHandle;
  38. OSType gTypeTag;
  39. Boolean gMore;
  40. PPCPortRec ourPort;
  41. PPCPortRefNum ourPortID;
  42. MyPPCRecPtrDeamon ourPPCPtr;
  43. PPCPortRec myPortName;
  44. LocationNameRec myLoc;
  45. Ptr readBuffer;
  46. Handle eventData;
  47. #define kGenStrings 128
  48. #define kPortName 132
  49. extern Boolean gReadPending;
  50. extern unsigned long gMySleep;
  51.  
  52. /* InformTheWorld opens our PPC port, and posts a PPCInform so other folks */
  53. /* can connect to us */
  54. Boolean InformTheWorld(void)
  55. {
  56.     Boolean result = false;
  57.     
  58.     OSErr myErr = noErr;
  59.     PPCOpenPBPtr localPtr;
  60.     localPtr = (PPCOpenPBPtr)ourPPCPtr;                     /* makes things more readable */
  61.     /* get a buffer to read stuff into */
  62.     /* first get a port, if we don't already have one */
  63.     if (ourPortID == nil) {
  64.         myErr = OpenAPort((PPCOpenPBPtr)ourPPCPtr);
  65.         if (myErr)
  66.             return(false);                                  /* we failed, die */
  67.         
  68.         ourPortID = localPtr->portRefNum;
  69.     }
  70.     DoInform((PPCInformPBPtr)ourPPCPtr);
  71.     
  72.     return(result);
  73. }
  74.  
  75. /* OpenAPort, uhhh, opens a port.  Opens our PPC port for others */
  76. /* to talk to us through */
  77. OSErr OpenAPort(PPCOpenPBPtr myPort)
  78. {
  79.     myPortName.nameScript = 0;
  80.     GetIndString(&myPortName.name,kGenStrings,kPortName);
  81.     myPortName.portKindSelector = ppcByCreatorAndType;
  82.     myPortName.u.port.creator = 'MOOB';
  83.     myPortName.u.port.type = 'APPL';
  84.     myPort->ioCompletion = (PPCCompProcPtr)OpenComplete;
  85.     
  86.     myPort->serviceType = ppcServiceRealTime;               /* only valid one under 7.0 */
  87.     myPort->resFlag = 0;
  88.     myPort->portName = &myPortName;
  89.     myPort->locationName = &myLoc;
  90.     myPort->networkVisible = false;                         /* NO, I don't want others using this service */
  91.     myLoc.locationKindSelector = ppcNoLocation;
  92.     
  93.     /* open syncrnouls */
  94.     return(PPCOpen(myPort, true));
  95.     
  96. }
  97.  
  98. /* PPCOpenPort */
  99.  
  100. /* DoInform posts a PPCInform, telling the world that we are ready to */
  101. /* accept data through our PPC channel */
  102. Boolean DoInform(PPCInformPBPtr p)
  103. {
  104.     
  105.     p->ioCompletion = (PPCCompProcPtr)InformComplete;
  106.     /* port reference number is already set in the Parameter Block */
  107.     /* most of this junk is already set */
  108.     p->portName = nil;
  109.     p->locationName = nil;
  110.     p->userName = nil;
  111.     p->autoAccept = true;   /* if true session will be accepted automatically */
  112.     /* instead of having to go through a PPCAccept.  I'm doing this primarly */
  113.     /* because this deamon is not network visible, so I don't thing anyone */
  114.     /* will be playing hijinks on us.  */
  115.     if (PPCInform(p, true) != noErr) {       
  116.         return false;
  117.     } else
  118.         return true;
  119. }
  120.  
  121. /* DoInform */
  122.  
  123. /* CloseOffTheWorld shuts things down when this app quits */
  124. void CloseOffTheWorld(void)
  125. {
  126.     PPCClosePBPtr closeRec = NewPtrClear(sizeof(PPCClosePBRec));
  127.     closeRec->ioCompletion = nil;
  128.     closeRec->ioResult = 0;
  129.     closeRec->portRefNum = ourPortID;
  130.     PPCClose(closeRec, false);
  131.     DisposPtr((Ptr)closeRec);
  132.     
  133.     
  134. }
  135.  
  136. /* I could post the PPC inform from here, but I decided not to in this case.  */
  137. /* Why?  I'm not sure. */
  138. void OpenComplete(PPCInformPBPtr p)
  139. {
  140. #pragma unused (p)
  141.     /* do nothing */
  142.     
  143. }
  144.  
  145. /* When this InformCompletion routine is hit, that means that someone has */
  146. /* invoked a PPCStart on our port.  Since we automatically accepted it, we */
  147. /* will begin reading from here.  If we wanted to authenticate, we'd do a PPCAccept */
  148. /* here (if we wanted to accept) and then start the read from the */
  149. /* PPCAccept completion routine. */
  150. void InformComplete(PPCReadPBPtr p)
  151. {
  152.     /* Start reading Bucky */
  153.     
  154.     p->ioCompletion = (PPCCompProcPtr)ReadComplete;
  155.     p->bufferPtr = readBuffer;
  156.     p->bufferLength = kOneK;
  157.     gMySleep = 1; /* bump the sleep time down so we can start processing faster */
  158.     /* so we can process the data after it's read */
  159.     /* since we won't go through WaitNextEvent and see the completion flag unless */
  160.     /* we bump the sleep time down a bit */
  161.     PPCRead((PPCReadPBPtr)p, true);
  162. }
  163.  
  164. /* When we hit this completion routine, it means one of two things; */
  165. /* 1) We are all done reading, and we are ready to send the event */
  166. /* or */
  167. /* 2) We've filled our PPC buffer (rememeber, it was only one K ) */
  168. /* and we need to swap that data to a safe place and read again */
  169. void ReadComplete(PPCReadPBPtr p)
  170. {
  171.     /* read completeed, deal with it */
  172.     gReadPending = true;
  173.     gMore = p->more;
  174.     gTypeTag = p->blockType;
  175.     gMySleep = 0;
  176. }
  177.  
  178. /* this processes the result of the last async read, and re-reads if */
  179. /* theres more data to get */
  180. /* It also checks to see if this is data we understand. In this case, MAVT type */
  181. /* data (which means My AppleeVenT), I set this type in the PPCWrite block */
  182. /* elsewhere.  If you don't do this, bad things will happen when you try */
  183. /* and do an AESend on data someone else sent */
  184. void CollectLastData(void)
  185. {
  186.     unsigned long currentSize;
  187.     AppleEvent theEvent;
  188.     AEDesc tempDesc;
  189.     PPCReadPBPtr localPtr = (PPCReadPBPtr)ourPPCPtr;
  190.     if (gMore) {
  191.         /* we need to move the current data into another buffer, and then read again */
  192.         currentSize = GetHandleSize(dataHandle);
  193.         SetHandleSize(dataHandle, currentSize + localPtr->actualLength);
  194.         HLock(dataHandle);
  195.         BlockMove(readBuffer, (*dataHandle) + currentSize, localPtr->actualLength);
  196.         HUnlock(dataHandle);
  197.         localPtr->ioCompletion = (PPCCompProcPtr)ReadComplete;
  198.         localPtr->bufferPtr = readBuffer;
  199.         localPtr->bufferLength = kOneK;
  200.         /* read more */
  201.         PPCRead((PPCReadPBPtr)localPtr, true);
  202.         
  203.     } else {
  204.         /* now we need to send the thing.  So send it, then re-post the inform */
  205.         /* there's no more, but we need to move what we have */
  206.         /* same as before */
  207.         if (gTypeTag == kMyTypeOfData) {
  208.             currentSize = GetHandleSize(dataHandle);
  209.             SetHandleSize(dataHandle, currentSize + localPtr->actualLength);
  210.             HLock(dataHandle);
  211.             BlockMove(readBuffer, (*dataHandle) + currentSize, localPtr->actualLength);
  212.             HUnlock(dataHandle);
  213.             
  214.             PPCEnd((PPCEndPBPtr)localPtr, false);
  215.             
  216.             gReadPending = false;
  217.             gMySleep = 200;                                 /* back to sleep */
  218.             /* now send the event we've so laboriously xfered */
  219.             /* you'll notice here that I am setting the descriptor type */
  220.             /* to 'aevt' and using some default interaction, reply, and */
  221.             /* timeout values.  To be more flexible, you should pass all these paramters */
  222.             /* as a 'header' block through PPC, see the Read Me file for more details */
  223.             /* I am doing this here for simpliciites sake */
  224.             theEvent.descriptorType = kCoreEventClass;
  225.             theEvent.dataHandle = dataHandle;
  226.             AESend(&theEvent, nil, kAECanInteract + kAENoReply + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout,
  227.                    (IdleProcPtr)nil, nil);
  228.             /* so we just sent the event. Normally, you'd call AEDisposeDesc on this thing, */
  229.             /* but in this case since it's our handle made by us, I'll just set it's size */
  230.             /* back to zero */
  231.         } else {
  232.             /* it was not my data type, so end the session */
  233.             PPCEnd((PPCEndPBPtr)localPtr, false);
  234.         }
  235.         SetHandleSize(dataHandle, 0);
  236.         /* Now we re-inform, we're ready for another message */
  237.         InformTheWorld();
  238.     }
  239. }
  240.  
  241.  
  242. #undef __BUILDINGDEAMON__
  243. #undef __AEDPPCSTUFF__
  244.